<?php
###
#  Baing PHP 框架 1.0.0
#  http://baing.co/
#
#  Copyright: 白晓阳
#  License: CC BY-NC-SA 4.0
#  https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh
###

namespace bai\resource\application;

use bai\feature\ExtensionException;


/**
 * <APCu>
 * Runtime
 * [
 *     'key' => 'key'
 *     'value' => 'value'
 *     'lifetime' => 1800 *
 *     'method' => 'method'
 * ]
 */
class NativeCache extends \bai\resource\Application
{
    public const LIFETIME = 1800;

    private const EXTENSION = 'APCu';

    public function run(array $runtime = [])
    {
        $key = $runtime['key'] ?? null;
        if ($key === null) return self::RUN_FAILED;
        $method = $runtime['method'] ?? self::GET;
        $call = strtolower($method);
        if ($method === self::GET || $method === self::DELETE) {
            return $this->$call($key);
        }
        if ($method === self::PATCH || $method === self::DELETE) {
            $value = $runtime['value'] ?? null;
            if ($value === null) return self::RUN_FAILED;
            $lifetime = $runtime['lifetime'] ?? $this->find('lifetime') ?? static::LIFETIME;
            return $this->$call($value, $key, $lifetime);
        }
        return self::RUN_FAILED;
    }

    public function get(string|array $key)
    {
        $result = apcu_fetch($key, $success);
        return [
            'status' => $success ? self::SUCCEEDED : self::FAILED,
            'result' => $success ? $result : null
        ];
    }

    public function post(string|array $value, ?string $key = null, int $lifetime = self::LIFETIME)
    {
        if (is_string($key)) {
            $result = apcu_add($key, $value, $lifetime);
            return ['status' => $result ? self::SUCCEEDED : self::FAILED];
        }

        $result = apcu_add($value, ttl: $lifetime);
        $status = empty($result) ? self::SUCCEEDED : (count($result) < count($value) ? self::INCOMPLETE : self::FAILED);
        return [
            'status' => $status,
            'result' => $result
        ];
    }

    public function put(string|array $value, ?string $key = null, int $lifetime = self::LIFETIME)
    {
        if (is_string($key)) {
            $result = apcu_store($key, $value, $lifetime);
            return ['status' => $result ? self::SUCCEEDED : self::FAILED];
        }

        $result = apcu_store($value, null, $lifetime);
        $status = empty($result) ? self::SUCCEEDED : (count($result) < count($value) ? self::INCOMPLETE : self::FAILED);
        return [
            'status' => $status,
            'result' => $result
        ];
    }

    public function delete(string|array $key)
    {
        if (is_string($key)) {
            $result = apcu_delete($key);
            return ['status' => $result ? self::SUCCEEDED : self::FAILED];
        }

        $deleted = apcu_delete($key);
        $result = array_diff($key, $deleted);
        $status = empty($result) ? self::SUCCEEDED : (count($result) < count($key) ? self::INCOMPLETE : self::FAILED);
        return [
            'status' => $status,
            'result' => $result
        ];
    }

    protected function init()
    {
        if (!extension_loaded(self::EXTENSION) || !apcu_enabled()) {
            throw new ExtensionException(self::EXTENSION);
        }
    }
}
